Wednesday, February 14, 2007

Flex tree's with a context menu

Recently on the flexcoders list a question was posed regarding how to get the item that was 'right-clicked on' when dealing with a tree. There are a few steps to follow if you plan to implement a context menu that is dynamic based on individual tree items.

First, you need to use the itemRollOver event of the <mx:Tree> component to track the last item that was rolled over, and save it to a variable for later use. Then when the ContextMenuEvent.MENU_SELECT event is triggered, you will refer back to this variable as it holds a reference to the itemRenderer and therefore the data you need access to.

You can view an example here and view the code here...

12 comments:

  1. beware ! rollover event continues to be launched after right button pressed and during the exploration of the context menu by the mouse. The result is a shift of the selected node in your tree !! If somebody knows the solution, thanks

    ReplyDelete
  2. Hi JPK,

    I just took a look at what you mentioned and have been unable to replicate the issue you point out. Can you provide more details of what you're running into?

    Have a good day,
    Michael

    ReplyDelete
  3. Anonymous11:50 PM

    The issue will happen while you use firefox.

    ReplyDelete
  4. Anonymous8:11 PM

    Hi,

    This is a nice little example. I extended it a little bit by having the right-click also cause the tree to make the item under the mouse become selected.

    I wanted to do this because it's the behavior of most desktop applications, e.g. windows explorer, and a lot of our users were getting confused with our flex app. I used the line:

    myTree.selectedItem = _lastTreeItem.itemRenderer.data;

    ... in the contextMenuTriggered function.

    Thanks,
    KaJun

    ReplyDelete
  5. Anonymous8:52 AM

    Can you show me the source with
    myTree.selectedItem = _lastTreeItem.itemRenderer.data;

    ReplyDelete
  6. Anonymous11:11 AM

    The Fix for Firefox is not too make sure that your clone the event on:

    function contectMenuTriggered(){
    var newListEvent : ListEvent = lastLastTreeItem.clone() as ListEvent;

    ...

    }

    This will snapshot item under the mouse at the time of right click and then not update as further rollovers accrue.

    ReplyDelete
  7. Hi,cool but the best is to set the ContextMenu of the TreeItemRenderer component, moreover, you should select the right clicked item:

    public function onItemRollOver(e:ListEvent):void
    {
    TreeItemRenderer(e.itemRenderer).contextMenu = myContextMenu;
    }

    ReplyDelete
  8. I made a custom TreeItemRenderer that sets a context menu using this.contextMenu = new ContextMenu();

    The ContextMenuItems have event listeners for ContextMenuEvent.MENU_ITEM_SELECT:

    var open:ContextMenuItem - new ContextMenuItem("Open Editor");
    open.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, openHandler)

    Then openHandler just does:
    dispatchEvent(new DataActionEvent(someName, MyWrapperClass(super.data).id);

    This sends the ID of the item the user selected with the event so that the application can take appropriate action depending on what the user selected when the menu was opened.

    ReplyDelete
  9. Guys, this discussion has solved my long standing problem of Tree component. Thanks to all of you :-)

    ReplyDelete
  10. This solution sometimes caused a endless loop. So I tried following:

    --
    private function onContextMenuTriggered(event:ContextMenuEvent):void {

    // Empty the items.
    this.contextMenu.customItems = new Array();

    var uiTextField:IUITextField = event.mouseTarget as IUITextField;
    if ((uiTextField != null) && (uiTextField.owner is IListItemRenderer)) {
    var itemRenderer:IListItemRenderer = uiTextField.owner as IListItemRenderer;
    var selectedIndex:int = this.itemRendererToIndex(itemRenderer); // this is a inherited tree
    this.selectedIndex = selectedIndex;
    } else {
    // Clicked target is part of the tree, but not an item.
    return;
    }

    ...

    ReplyDelete
  11. Anonymous5:49 AM

    Cool example...
    Is there any way of hiding the built-in items on right-click?


    Thanks
    Aruna

    ReplyDelete
  12. Not that I'm aware of...

    ReplyDelete